package com.myself.cloud.service.config;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.support.spring.PropertyPreFilters;
import com.myself.cloud.util.JsonUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.*;
import org.slf4j.MDC;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import java.text.SimpleDateFormat;
import java.util.UUID;

@Aspect
@Component
@Slf4j
public class LogAspect {
    @Pointcut("execution(public * com.myself.cloud.service.controller..*Controller.*(..))")
    public void controllerPointcut() {
    }

    @Before("controllerPointcut()")
    public void doBefore(JoinPoint joinPoint) {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        SimpleDateFormat df = new SimpleDateFormat("yyyyMMddHHmmssSSS");
        Signature signature = joinPoint.getSignature();
        String name = signature.getName();
        log.info("请求地址: {} {},类名方法: {}.{}", request.getRequestURL().toString(), request.getMethod(),
                signature.getDeclaringTypeName(), name);
        Object[] args = joinPoint.getArgs();
        Object[] arguments = new Object[args.length];
        for (int i = 0; i < args.length; i++) {
            if (args[i] instanceof ServletRequest || args[i] instanceof ServletResponse || args[i] instanceof MultipartFile) {
                continue;
            }
            arguments[i] = args[i];
        }
        String[] excludeProperties = {"password", "file"};
        PropertyPreFilters filters = new PropertyPreFilters();
        PropertyPreFilters.MySimplePropertyPreFilter excludeFilter = filters.addFilter();
        excludeFilter.addExcludes(excludeProperties);
        log.info("请求参数: \n{}", JsonUtil.JsonFormart(JSONObject.toJSONString(arguments, excludeFilter)));
    }

    @Around("controllerPointcut()")
    public Object doAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        long startTime = System.currentTimeMillis();
        Object result = null;
        result = proceedingJoinPoint.proceed();
        String[] excludeProperties = {"password", "file"};
        PropertyPreFilters filters = new PropertyPreFilters();
        PropertyPreFilters.MySimplePropertyPreFilter excludeFilter = filters.addFilter();
        excludeFilter.addExcludes(excludeProperties);
        log.info("返回结果: \n{}", JsonUtil.JsonFormart(JSONObject.toJSONString(result, excludeFilter)));
        log.info("------ 结束 耗时:{} ms -------------", System.currentTimeMillis() - startTime);
        return result;
    }

    /**
     * 抛出通知
     *
     * @param e
     */
    @AfterThrowing(pointcut = "controllerPointcut()", throwing = "e")
    public void afterThrowable(Throwable e) {
        log.info("发成异常:{}", e.getMessage());
    }
}
